package kk.learn.bigdata.zkmysqlconfig;


import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.I0Itec.zkclient.IZkDataListener;
import org.I0Itec.zkclient.ZkClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * <p>
 * 引流的客户 前端控制器
 * </p>
 *
 * @author KK
 * @since 2020-04-21
 */
@RestController
@RequestMapping("/demo")
public class DemoController {


    private HikariDataSource ds;

    @SuppressWarnings("FieldCanBeLocal")
    private ZkClient zkClient;

    @PostConstruct
    public void initDbPool() throws SQLException {
        // 启动的时候初始化数据源
        System.out.println("开始启动mysql数据源");

        // 初始化zkClient
        zkClient = new ZkClient("linux121:2181,linux122:2181");
        zkClient.setZkSerializer(new ZkStrSerializer());

        // 读取mysql-config节点的数据
        if (!zkClient.exists("/mysql-config")) {
            throw new RuntimeException("zk上没有mysql配置， 无法启动服务器");
        }
        String mysqlUrl = zkClient.readData("/mysql-config");
        ds = new HikariDataSource(getDsConfig(mysqlUrl));
       // 展示当前在那个数据库中
        System.out.println("当前数据库：" + getCurrentDatabase());





        // 为mysql-config节点配置一个data change 类型的substriber
        zkClient.subscribeDataChanges("/mysql-config", new IZkDataListener() {
            public void handleDataChange(String path, Object data) throws Exception {
                // 当mysql-config节点的配置改变时， 根据新的信息修改mysql 连接池配置
                ds.close();
                ds = new HikariDataSource(getDsConfig((String) data));
                // 展示当前在那个数据库中
                System.out.println("当前数据库：" + getCurrentDatabase());
            }

            public void handleDataDeleted(String path)  {
            }
        });

    }

    @PreDestroy
    public void destroy(){
        zkClient.close();
        ds.close();
    }


    private HikariConfig getDsConfig(String mysqlUrl) {
        // 根据配置创建连接池
        HikariConfig config = new HikariConfig();
//        jdbc:mysql://localhost:3306/test2?characterEncoding=utf8&user=test2&password=test2
//        config.setJdbcUrl("jdbc:mysql://localhost:3306/test1?characterEncoding=utf8&user=test1&password=test1");
        config.setJdbcUrl(mysqlUrl);
        config.addDataSourceProperty("cachePrepStmts", "true");
        config.addDataSourceProperty("prepStmtCacheSize", "250");
        config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
        return config;
    }



    private String getCurrentDatabase() throws SQLException {
        @SuppressWarnings({"SqlNoDataSourceInspection", "SqlResolve"})
        String sql = "select dummy_row from dummy";
        final Connection connection = ds.getConnection();
        try (PreparedStatement ps = connection.prepareStatement(sql)) {
            ResultSet resultSet = ps.executeQuery();
            resultSet.next();
            return resultSet.getString("DUMMY_ROW");
        }
    }


    @GetMapping
    public String demo() throws SQLException {
        String msg = "当前数据库：" + getCurrentDatabase();
        System.out.println(msg);
        return msg;
    }




}
